package system

import (
	"MoSkeleton/framework"
	"MoSkeleton/framework/core/consts"
	"MoSkeleton/framework/core/dto/response"
	"MoSkeleton/framework/utils"
	system2 "MoSkeleton/models/system"
	"MoSkeleton/services"
	system3 "MoSkeleton/web/pogos/request/system"
	"MoSkeleton/web/pogos/response/system"
	"MoSkeleton/web/v1/http/base"
	"github.com/gin-gonic/gin"
	"github.com/samber/lo"
	"go.uber.org/zap"
	"strconv"
)

type SysMenuCtrl struct {
	base.BaseCtrl
}

func (s *SysMenuCtrl) GetCtrlTitle() string {
	msg, _ := utils.Translater.Translate(consts.TKey_TitleSysMenuMsg)
	return msg
}

// GetRouters 获取路由
// @Tags 菜单管理
// @Summary 获取路由
// @Security ApiKeyAuth
// @Success 200 {object} response.Response{data=[]system.RouterResp} "{"code": 200, "data": [...]}"
// @Router /system/menu/routers [get]
func (s *SysMenuCtrl) GetRouters(c *gin.Context) {
	menuTree, err := services.ServiceGroupInst.SystemGroupInst.SysMenuServiceInst.GetMenuTreeByUserId(utils.GetUserIdFromGin(c))
	if err != nil {
		framework.MoLogger.Error("获取菜单树失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommSelectFailCode, consts.TKey_MenuGetAllFailMsg)
		return
	}
	routerResp := services.ServiceGroupInst.SystemGroupInst.SysMenuServiceInst.BuildRouterByMenuTree(menuTree)
	response.SuccessAsI18n(c, consts.TKey_CommGetSuccessMsg, routerResp)
}

// GetMenuAll 获取菜单列表
// @Tags 菜单管理
// @Summary 获取菜单列表
// @Security ApiKeyAuth
// @Param data  query  system.SysMenuListReq  true  "请求参数"
// @Success 200 {object} response.Response{data=[]system.SysMenuItemResp} "{"code": 200, "data": [...]}"
// @Router /system/menu/list [get]
func (s *SysMenuCtrl) GetMenuAll(c *gin.Context) {
	listReq := system3.SysMenuListReq{}
	if err := c.ShouldBind(&listReq); err != nil {
		framework.MoLogger.Error("参数绑定失败", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	menuList, err := services.ServiceGroupInst.SystemGroupInst.SysMenuServiceInst.GetAllMenuByUserId(&listReq, utils.GetUserIdFromGin(c))
	if err != nil {
		framework.MoLogger.Error("获取菜单列表失败", zap.Error(err))
		response.FailErrorWithCode(c, err, consts.CommSelectFailCode, consts.TKey_MenuGetListFailMsg)
		return
	}

	menuItemsResp := lo.Map(menuList, func(menu *system2.SysMenu, index int) *system.SysMenuItemResp {
		menuItem := &system.SysMenuItemResp{}

		_ = utils.CopyStruct(menuItem, menu)
		return menuItem
	})
	response.SuccessAsI18n(c, consts.TKey_CommGetSuccessMsg, menuItemsResp)
}

// GetMenuById 获取菜单详情
// @Tags 菜单管理
// @Summary 获取菜单详情
// @Security ApiKeyAuth
// @Param id path  string  true  "菜单id"
// @Success 200 {object} response.Response{data=system.SysMenuItemResp} "{"code": 200, "data": [...]}"
// @Router /system/menu/{id} [get]
func (s *SysMenuCtrl) GetMenuById(c *gin.Context) {
	idStr := c.Param("id")
	if id, err := strconv.ParseUint(idStr, 10, 64); err != nil {
		framework.MoLogger.Error("参数转换失败", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	} else {
		menu, err := services.ServiceGroupInst.SystemGroupInst.SysMenuServiceInst.GetMenuById(id)
		if err != nil {
			framework.MoLogger.Error("获取菜单失败", zap.Error(err))
			response.FailErrorWithCodeAsI18n(c, err, consts.CommSelectFailCode, consts.TKey_MenuGetFailMsg)
			return
		}
		itemResp := &system.SysMenuItemResp{}
		if err := utils.CopyStruct(itemResp, menu); err != nil {
			framework.MoLogger.Error("对象拷贝失败", zap.Error(err))
			response.FailMsgAsI18n(c, consts.CommSelectFailCode, consts.TKey_CommCopyFailMsg)
			return
		}
		response.SuccessAsI18n(c, consts.TKey_CommGetSuccessMsg, itemResp)
	}
}

// AddMenu 添加菜单
// @Tags 菜单管理
// @Summary 添加菜单
// @Security ApiKeyAuth
// @Param data body  system.SysMenuAddReq  true  "请求参数"
// @Success 200 {object} response.Response{data=system.SysMenuItemResp} "{"code": 200, "data": [...]}"
// @Router /system/menu [post]
func (s *SysMenuCtrl) AddMenu(c *gin.Context) {
	addReq := system3.SysMenuAddReq{}
	if err := c.ShouldBindJSON(&addReq); err != nil {
		framework.MoLogger.Error("参数绑定失败", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	addReq.CreatedBy = utils.GetUsernameFromGin(c)
	addReq.UpdatedBy = addReq.CreatedBy
	if ok, err := services.ServiceGroupInst.SystemGroupInst.SysMenuServiceInst.AddMenuById(&addReq); err != nil {
		framework.MoLogger.Error("添加菜单失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommCreatFailCode, consts.TKey_MenuAddFailMsg)
		return
	} else if !ok {
		response.FailMsgAsI18n(c, consts.CommCreatFailCode, consts.TKey_MenuAddFailMsg)
		return
	}
	response.SuccessAsI18n(c, consts.TKey_CommCreatSuccessMsg, nil)
}

// UpdateMenuById 更新菜单
// @Tags 菜单管理
// @Summary 更新菜单
// @Security ApiKeyAuth
// @Param data body  system.SysMenuUpdateReq  true  "请求参数"
// @Success 200 {object} response.Response{data=system.SysMenuItemResp} "{"code": 200, "data": [...]}"
// @Router /system/menu [put]
func (s *SysMenuCtrl) UpdateMenuById(c *gin.Context) {
	updateReq := system3.SysMenuUpdateReq{}
	if err := c.ShouldBindJSON(&updateReq); err != nil {
		framework.MoLogger.Error("参数错误", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	updateReq.UpdatedBy = utils.GetUsernameFromGin(c)
	if ok, err := services.ServiceGroupInst.SystemGroupInst.SysMenuServiceInst.UpdateMenuById(&updateReq); err != nil {
		framework.MoLogger.Error("更新菜单失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommUpdateFailCode, consts.TKey_MenuUpdateFailMsg)
		return
	} else if !ok {
		response.FailMsgAsI18n(c, consts.CommUpdateFailCode, consts.TKey_MenuUpdateFailMsg)
		return
	}
	response.SuccessAsI18n(c, "操作成功", nil)
}

// DeleteById 删除菜单
// @Tags 菜单管理
// @Summary 删除菜单
// @Security ApiKeyAuth
// @Param id path string true  "id"
// @Success 200 {object} response.Response{data=system.SysMenuItemResp} "{"code": 200, "data": [...]}"
// @Router /system/menu/{id} [delete]
func (s *SysMenuCtrl) DeleteById(c *gin.Context) {
	idStr := c.Param("id")
	if id, err := strconv.ParseUint(idStr, 10, 64); err != nil {
		framework.MoLogger.Error("参数转换失败", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	} else {
		if _, err := services.ServiceGroupInst.SystemGroupInst.SysMenuServiceInst.DeleteById(id); err != nil {
			framework.MoLogger.Error("删除菜单失败", zap.Error(err))
			response.FailErrorWithCodeAsI18n(c, err, consts.CommDeleteFailCode, consts.TKey_MenuUpdateFailMsg)
			return
		}
	}
	response.SuccessAsI18n(c, consts.TKey_CommDeleteSuccessMsg, nil)
}

// Treeselect 获取菜单树
// @Tags 菜单管理
// @Summary 获取菜单树
// @Security ApiKeyAuth
// @Param data query  system.SysMenuListReq  true  "请求参数"
// @Success 200 {object} response.Response{data=system.SysMenuItemResp} "{"code": 200, "data": [...]}"
// @Router /system/menu/treeselect [get]
func (s *SysMenuCtrl) Treeselect(c *gin.Context) {
	listReq := system3.SysMenuListReq{}
	if err := c.ShouldBind(&listReq); err != nil {
		framework.MoLogger.Error("参数绑定失败", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	menuList, err := services.ServiceGroupInst.SystemGroupInst.SysMenuServiceInst.GetAllMenuByUserId(&listReq, utils.GetUserIdFromGin(c))
	if err != nil {
		framework.MoLogger.Error("获取菜单列表失败", zap.Error(err))
		response.FailErrorWithCode(c, err, consts.CommSelectFailCode, consts.TKey_MenuGetListFailMsg)
		return
	}
	if menuTree, err := services.ServiceGroupInst.SystemGroupInst.SysMenuServiceInst.BuildMenuTreeSelect(menuList); err != nil {
		framework.MoLogger.Error("构建菜单树失败", zap.Error(err))
		response.FailErrorWithCode(c, err, consts.CommSelectFailCode, consts.TKey_MenuBuildTreeFailMsg)
		return
	} else {
		response.SuccessAsI18n(c, consts.TKey_CommGetSuccessMsg, menuTree)
	}
}

// RoleMenuTreeselect 获取角色菜单树
// @Tags 菜单管理
// @Summary 获取角色菜单树
// @Security ApiKeyAuth
// @Param roleId path  string  true  "角色"
// @Success 200 {object} response.Response{data=system.SysMenuItemResp} "{"code": 200, "data": [...]}"
// @Router /system/menu/roleMenuTreeselect/{roleId} [get]
func (s *SysMenuCtrl) RoleMenuTreeselect(c *gin.Context) {
	userId := utils.GetUserIdFromGin(c)
	roleIdStr := c.Param("roleId")
	roleId, err := strconv.ParseUint(roleIdStr, 10, 64)
	if err != nil {
		framework.MoLogger.Error("参数转换失败", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	result := make(map[string]interface{})
	listReq := new(system3.SysMenuListReq)
	if sysMenus, err := services.ServiceGroupInst.SystemGroupInst.SysMenuServiceInst.GetAllMenuByUserId(listReq, userId); err != nil {
		framework.MoLogger.Error("获取菜单列表失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommSelectFailCode, consts.TKey_MenuGetListFailMsg)
		return
	} else {
		tss, err := services.ServiceGroupInst.SystemGroupInst.SysMenuServiceInst.BuildMenuTreeSelect(sysMenus)
		if err != nil {
			framework.MoLogger.Error("构建菜单树失败", zap.Error(err))
			response.FailErrorWithCodeAsI18n(c, err, consts.CommSelectFailCode, consts.TKey_MenuBuildTreeFailMsg)
			return
		}
		result["menus"] = tss
	}
	if menuIds, err := services.ServiceGroupInst.SystemGroupInst.SysMenuServiceInst.GetMenuListByRoleId(roleId); err != nil {
		framework.MoLogger.Error("获取角色菜单权限失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommSelectFailCode, consts.TKey_MenuGetRoleListFailMsg)
		return
	} else {
		result["checkedKeys"] = menuIds
	}
	response.SuccessAsI18n(c, consts.TKey_CommGetSuccessMsg, result)
}
